#include "wss.h"
#include "part.h"

wss_device wss;

#define WSS_RETURN "OK|CER|AER|RER|VER"
#define WSS_OK     "OK"
#define WSS_BUF_LENGTH  1024

char* wss_file = "./config/wss_config";
char* wss_file_back = "./config/wss_config_bak";

void wss_sample_timer(void* param);
int wss_set_workmode(wss_device* p_wss,char* mode);
int wss_set_spacing(wss_device* p_wss,int spacing,clock_t* time);

int read_hardware_release_wss(wss_device* p_wss);
int read_firmdware_release_wss(wss_device* p_wss);
int read_serial_number_wss(wss_device* p_wss);
int read_manufacturing_date_wss(wss_device* p_wss);
int read_module_id_wss(wss_device* p_wss);
int read_case_temperature_wss(wss_device* p_wss);
int read_internal_temperature_wss(wss_device* p_wss);
int read_operational_status_wss(wss_device* p_wss);
int read_hardware_status_wss(wss_device* p_wss);
int read_latched_status_wss(wss_device* p_wss);

int init_wss_device(wss_device* p_wss){
    p_wss->busy = 1;
    wss_set_workmode(p_wss,"SLS");
    // wss_set_spacing(p_wss,p_wss->channel_spacing,NULL);
    // wss_set_custom(p_wss,p_wss->slices,p_wss->slices_count,NULL);
    read_hardware_release_wss(p_wss);
    read_firmdware_release_wss(p_wss);
    read_serial_number_wss(p_wss);
    read_manufacturing_date_wss(p_wss);
    read_module_id_wss(p_wss);
    p_wss->busy = 0;
}

void init_wss(wss_device* p_wss){
    if(p_wss == NULL) return;
    memset(p_wss,0,sizeof(wss_device));
    p_wss->uart_fd = open_uart("/dev/ttymxc7",115200,8,'N',2);
    p_wss->timer = timer_start(wss_sample_timer,SAMPLE_TIME,p_wss,1);
    p_wss->print_flag = print_wss;
    p_wss->device_name = "wss";
    wss_load_config(p_wss,0);
}

void wss_save_config(wss_device* p_wss, int is_back){
    FILE* fp;
    int size = 0;
    if(is_back){
        fp = fopen(wss_file_back,"w");
    }
    else{
        fp = fopen(wss_file,"w");
    }
    if(fp == NULL) return;
    size = OFFSET(wss_device,save_end) - OFFSET(wss_device,save_begin);
    fwrite((void*)&p_wss->save_begin,size,1,fp);
    fclose(fp);
}

int wss_load_config(wss_device* p_wss, int is_back){
    FILE* fp;
    int size = 0;
    char cmd[64] = {0};
    if(is_back){
        fp = fopen(wss_file_back,"r");
        if(fp){
            sprintf(cmd,"cp %s %s",wss_file_back,wss_file);
            system(cmd);
        }
    }
    else{
        fp = fopen(wss_file,"r");
    }
    if(fp == NULL) return 0;
    size = OFFSET(wss_device,save_end) - OFFSET(wss_device,save_begin);
    fread((void*)&p_wss->save_begin,size,1,fp);
    fclose(fp);
    return 1;
}

void wss_alarm_register(device_alarm_list* p_list){
    alram_info_register(p_list,&wss.alarm_info.oss.module_restarted,"latched restarted!","latchedRestarted","wss");
    alram_info_register(p_list,&wss.alarm_info.oss.optics_not_ready,"optical unit's temperature is not stable!","opticsNotReady","wss");
    alram_info_register(p_list,&wss.alarm_info.oss.start_up_active,"unit is starting up!","startUpActive","wss");
    alram_info_register(p_list,&wss.alarm_info.hss.case_temp,"hardware case operating temperature exceeded!","hCaseTemp","wss");
    alram_info_register(p_list,&wss.alarm_info.hss.internal_temp,"hardware internal temperature exceeded!","hInternalTemp","wss");
    alram_info_register(p_list,&wss.alarm_info.hss.temp_control,"hardware temperature out of control!","hTempControl","wss");
    alram_info_register(p_list,&wss.alarm_info.hss.thermal_shutdown,"hardware thermal limits exceeded for the device!","hThermalShutdown","wss");
    alram_info_register(p_list,&wss.alarm_info.hss.power_supply,"hardware 5V rail issue!","hPowerSupply","wss");
    alram_info_register(p_list,&wss.alarm_info.hss.vcom_control,"hardware VCOM control loop failure!","hVcomControl","wss"); 
    alram_info_register(p_list,&wss.alarm_info.hss.power_rail,"hardware internal power rail issue!","hPowerRail","wss"); 
    alram_info_register(p_list,&wss.alarm_info.lss.case_temp,"latched hardware case operating temperature exceeded!","lCaseTemp","wss");
    alram_info_register(p_list,&wss.alarm_info.lss.internal_temp,"latched hardware internal temperature exceeded!","lInternalTemp","wss");
    alram_info_register(p_list,&wss.alarm_info.lss.temp_control,"latched hardware temperature out of control!","lTempControl","wss");
    alram_info_register(p_list,&wss.alarm_info.lss.thermal_shutdown,"latched hardware thermal limits exceeded for the device!","lThermalShutdown","wss");
    alram_info_register(p_list,&wss.alarm_info.lss.power_supply,"latched hardware 5V rail issue!","lPowerSupply","wss");
    alram_info_register(p_list,&wss.alarm_info.lss.vcom_control,"latched hardware VCOM control loop failure!","lVcomControl","wss"); 
    alram_info_register(p_list,&wss.alarm_info.lss.power_rail,"latched hardware internal power rail issue!","lPowerRail","wss"); 
}

int read_hardware_release_wss(wss_device* p_wss){
    char recv[32] = {0};
    int b,e;
    if(send_to_wss(p_wss,"HWR?",recv,1024,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            if(find_key("[0-9]+\\.[0-9]+\\.[0-9]+",recv,&b,&e,0,0)){
                strncpy(p_wss->fpga_version,recv+b,e-b);
                return 1;
            }            
        }
    }
    return 0;
}

int read_firmdware_release_wss(wss_device* p_wss){
    char recv[32] = {0};
    int b,e;
    if(send_to_wss(p_wss,"FWR?",recv,1024,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            if(find_key("[0-9]+\\.[0-9]+\\.[0-9]+(_rc)?[0-9]*",recv,&b,&e,0,0)){
                strncpy(p_wss->firmware_version,recv+b,e-b);
                return 1;
            }            
        }
    }
    return 0;
}

int read_serial_number_wss(wss_device* p_wss){
    char recv[1024] = {0};
    int b,e;
    if(send_to_wss(p_wss,"SNO?",recv,1024,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            if(find_key("(EP|EF|SN)[0-9]*",recv,&b,&e,0,0)){
                strncpy(p_wss->serial_number,recv+b,e-b);
                return 1;
            }            
        }
    }
    return 0;   
}

int read_manufacturing_date_wss(wss_device* p_wss){
    char recv[1024] = {0};
    int b,e;
    if(send_to_wss(p_wss,"MFD?",recv,1024,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            if(find_key("[0-9]*-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)-[0-9]*",recv,&b,&e,0,0)){
                strncpy(p_wss->manufacturing_date,recv+b,e-b);
                return 1;
            }            
        }
    }
    return 0; 
}

int read_module_id_wss(wss_device* p_wss){
    char recv[1024] = {0};
    int b,e;
    if(send_to_wss(p_wss,"MID?",recv,1024,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            if(find_key("\\^(\\w*)\\$",recv,&b,&e,1,1)){
                strncpy(p_wss->module_id,recv+b,e-b);
                return 1;
            }            
        }
    }
    return 0;  
}

cJSON* wss_packet(int id,int error_code,cJSON* param,int time){
    return response_packet(id,error_code,param,time);
}

void wss_sample_timer(void* param){
    wss_device* p_wss = (wss_device*)param;
    p_wss->sample_flag = 1;
}

void wss_sample(wss_device* p_wss){
    int ret;
    char buff[32] = {0};
    char temp[6] = {0};

    uint32_t status;
    if(p_wss->busy) return;
    p_wss->busy = 1;
    if(set_test_wss(p_wss)){
        ret = send_to_wss(p_wss,"OSS?",buff,32,5,NULL);    
        if(find_key(WSS_OK,buff,NULL,NULL,0,0)){
            find_keys("0x([0-9a-f]+)",buff,1,temp);
            sscanf(temp,"%x",&status);
            p_wss->alarm_info.oss.ready = (status>>0)&0x1;
            p_wss->alarm_info.oss.hss = (status>>1)&0x1;
            p_wss->alarm_info.oss.lss = (status>>2)&0x1;
            p_wss->alarm_info.oss.module_restarted = (status>>3)&0x1;
            p_wss->alarm_info.oss.optics_not_ready = (status>>5)&0x1;
            p_wss->alarm_info.oss.loading_calibration = (status>>6)&0x1;
            p_wss->alarm_info.oss.start_up_active = (status>>7)&0x1;
        }  
        ret = send_to_wss(p_wss,"HSS?",buff,32,5,NULL);    
        if(find_key(WSS_OK,buff,NULL,NULL,0,0)){
            find_keys("0x([0-9a-f]+)",buff,1,temp);
            sscanf(temp,"%x",&status);
            p_wss->alarm_info.hss.case_temp = (status>>0)&0x1;
            p_wss->alarm_info.hss.internal_temp = (status>>1)&0x1;
            p_wss->alarm_info.hss.temp_control = (status>>2)&0x1;
            p_wss->alarm_info.hss.vcom_control = (status>>6)&0x1;
            p_wss->alarm_info.hss.thermal_shutdown = (status>>7)&0x1;
            p_wss->alarm_info.hss.power_supply = (status>>8)&0x1;
            p_wss->alarm_info.hss.power_rail = (status>>9)&0x1;
        } 
        ret = send_to_wss(p_wss,"LSS?",buff,32,5,NULL);    
        if(find_key(WSS_OK,buff,NULL,NULL,0,0)){
            find_keys("0x([0-9a-f]+)",buff,1,temp);
            sscanf(temp,"%x",&status);
            p_wss->alarm_info.lss.case_temp = (status>>0)&0x1;
            p_wss->alarm_info.lss.internal_temp = (status>>1)&0x1;
            p_wss->alarm_info.lss.temp_control = (status>>2)&0x1;
            p_wss->alarm_info.lss.vcom_control = (status>>6)&0x1;
            p_wss->alarm_info.lss.thermal_shutdown = (status>>7)&0x1;
            p_wss->alarm_info.lss.power_supply = (status>>8)&0x1;
            p_wss->alarm_info.lss.power_rail = (status>>9)&0x1;
        }          
    }
    p_wss->busy = 0;
}

uint16_t check_summing(char* data){
    int len,i;
    uint16_t sum = 0;
    if(data == NULL) return 0;
    len = strlen(data);
    for(i=0;i<len;i++){
        sum += data[i];
    }
    return (~sum + 1);
}

void packet_wss_protocol(char* data,char* out_buf){
    char buf[8];
    uint16_t check_sum;
    strcat(out_buf,"^");
    strcat(out_buf,data);
    strcat(out_buf,"$");
    check_sum = check_summing(data);
    sprintf(buf,"%4X\r\n",check_sum);
    strcat(out_buf,buf);
}

void slices_to_string(wss_slices* slices,int size,char* string){
    int i;
    char buf[20];
    for(i=0;i<size;i++){  
        sprintf(buf,"%d=%d:%d;",slices[i].channel,
                                      slices[i].begin,
                                      slices[i].end);       
        strcat(string,buf);        
    }
    i = strlen(string)-1;
    string[i] = 0;
}

//"^1=1:8,1:10;10=9:12,8:15;3=14:17,10:20;9=350:373,340:380;$F476\r\n"
void string_to_slices(char* string,wss_slices* slices,int* size){
    int s,e,count = 0,i=0,index=0;
    char buf[32] = {0};

    while(find_key("[0-9]+=[0-9]+:[0-9]+",string + count,&s,&e,0,0)){        
        memcpy(buf,&string[s+count],e-s);
        buf[e-s] = 0;                        
        sscanf(buf,"%d=%d:%d",&slices[index].channel,
                                    &slices[index].begin,
                                    &slices[index].end
                              );                
        index++; 
        count += e;        
    }
    if(size) *size = index;
}

void channel_to_string(wss_channel* channel,int size,char* string){
    int i;
    char buf[20];
    for(i=0;i<size;i++){  
        sprintf(buf,"%d,%d,%0.1f;",channel[i].channel,channel->port,channel->atten);       
        strcat(string,buf);        
    }
    i = strlen(string)-1;
    string[i] = 0;
}

//"^1,2,7.8;2,3,0.9;1,2,0.0;1,2,0.0;1,2,0.0;1,2,0.0;1,2,0.0;7,212,12.25$F88A\r\n"
void string_to_channel(char* string,wss_channel* channels,int* size){
    int s,e,count = 0,i=0,index=0;
    char buf[32] = {0};

    while(find_key("[0-9]+,[0-9]+,[0-9]+\\.[0-9]+",string + count,&s,&e,0,0)){        
        memcpy(buf,&string[s+count],e-s);
        buf[e-s] = 0;                        
        sscanf(buf,"%d,%d,%f",&channels[index].channel,
                              &channels[index].port,
                              &channels[index].atten);                
        index ++; 
        count += e;        
    }
    if(size) *size = index;
}

int send_to_wss(wss_device* p_wss,char* cmd,char* recv_buf,int rlen,int32_t timeout,clock_t* usage_time){
    char send_buf[WSS_BUF_LENGTH] = {0};
    int ret = 0;
    packet_wss_protocol(cmd,send_buf);
    ret = query_tty_time((device*)p_wss,send_buf,strlen(send_buf),recv_buf,rlen,timeout,0,usage_time);
    if(ret > 0) return ret;
    return 0;
}

//--------------------------
int store_data(wss_device* p_wss){
    char recv[32] = {0};
    if(send_to_wss(p_wss,"STR",recv,32,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
           return 1;
        }
    }
    return 0;    
}

int wss_set_workmode(wss_device* p_wss,char* mode){    
    char recv[32] = {0};
    if(send_to_wss(p_wss,mode,recv,32,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            store_data(p_wss);
            return 1;
        }
    }
    return 0;
}

cJSON* packet_channel_spacing(wss_device* p_wss,int space){
    cJSON* param = cJSON_CreateObject();    
    cJSON_AddItemToObject(param,"space",cJSON_CreateNumber(space));
    return param;     
}

cJSON* get_channel_spacing_wss(wss_device* p_wss){
    char recv[32] = {0};
    char s_space[8] = {0};
    int i_space = 0;
    if(send_to_wss(p_wss,"CHR?",recv,32,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            find_keys("\\^(0|50|100)\\$",recv,1,s_space);
            i_space = atoi(s_space);            
            return wss_packet(id_wss_get_channel_spacing,COMM_TIMEOUT,packet_channel_spacing(p_wss,i_space),0);
        }
    }
    return wss_packet(id_wss_get_channel_spacing,COMM_TIMEOUT,NULL,0);    
}

int wss_set_spacing(wss_device* p_wss,int spacing,clock_t* time){
    char send[32] = {0};
    char recv[32] = {0};
    sprintf(send,"CHW %d",spacing);
    if(send_to_wss(p_wss,send,recv,32,5,time)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            store_data(p_wss);
            return 1;
        }
    }
    return 0;    
}

cJSON* set_channel_spacing_wss(wss_device* p_wss,cJSON* param){
    cJSON* item;
    clock_t time;
    int i,space = 50;
    char send[WSS_BUF_LENGTH];
    char recv[32];

    item = cJSON_GetObjectItem(param,"space");
    if(item){
        space = item->valueint;
        if(wss_set_spacing(p_wss,space,&time)){
            p_wss->channel_spacing = space;
            wss_save_config(p_wss,0);
            return wss_packet(id_wss_set_channel_spacing,NO_ERROR,param,time);
        }
    }
    return wss_packet(id_wss_set_channel_spacing,COMM_TIMEOUT,param,0);
}

cJSON* packet_cunstom_channel(wss_device* p_wss,char* custom_channel){
    wss_slices slices[WSS_CHANNEL_NUMBER] = {0};
    int i,size;
    cJSON *param,*array,*item;
    string_to_slices(custom_channel,slices,&size);
    param = cJSON_CreateObject();
    array = cJSON_CreateArray();
    if(size > 0){       
        for(i=0;i<size;i++){
            item = cJSON_CreateObject();
            cJSON_AddItemToObject(item,"channel",cJSON_CreateNumber(slices->channel));
            cJSON_AddItemToObject(item,"begin",cJSON_CreateNumber(slices->begin));
            cJSON_AddItemToObject(item,"end",cJSON_CreateNumber(slices->end));
            cJSON_AddItemToArray(array,item);
        }        
    }
    cJSON_AddItemToObject(param,"infos",array);
    return param; 
}

cJSON* get_custom_channel_wss(wss_device* p_wss){
    char recv[WSS_BUF_LENGTH] = {0};
    if(send_to_wss(p_wss,"DCC?",recv,WSS_BUF_LENGTH,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){            
            return wss_packet(id_wss_get_custom_channel,COMM_TIMEOUT,packet_cunstom_channel(p_wss,recv),0);
        }
    }
    return wss_packet(id_wss_get_custom_channel,COMM_TIMEOUT,NULL,0);    
}

int wss_set_custom(wss_device* p_wss,wss_slices* slices,int size,clock_t* time){
    char send[WSS_BUF_LENGTH] = {0};
    char recv[32] = {0}; 
    slices_to_string(slices,size,send);
    sprintf(send,"DCC %s",send);
    if(send_to_wss(p_wss,send,recv,32,5,time)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){ 
            store_data(p_wss);           
            return 1;
        }
    }
    return 0;    
}

cJSON* set_custom_channel_wss(wss_device* p_wss,cJSON* param){
    cJSON  *item,*array,*data;
    clock_t time;
    int i,size;
    char send[WSS_BUF_LENGTH];
    char recv[32];
    wss_slices slices[WSS_CHANNEL_NUMBER] = {0};

    array = cJSON_GetObjectItem(param,"infos");
    if(array){
        size = cJSON_GetArraySize(array);
        for(i=0;i<size;i++){
            item = cJSON_GetArrayItem(array,i);
            data = cJSON_GetObjectItem(item,"channel");
            slices[i].channel = data->valueint;
            item = cJSON_GetArrayItem(array,i);
            data = cJSON_GetObjectItem(item,"begin");
            slices[i].begin = data->valueint;
            item = cJSON_GetArrayItem(array,i);
            data = cJSON_GetObjectItem(item,"end");
            slices[i].end = data->valueint;
        }
        if(wss_set_custom(p_wss,slices,size,&time)){
            memcpy(p_wss->slices,slices,sizeof(slices)*size);
            p_wss->slices_count = size;        
            wss_save_config(p_wss,0);
            return wss_packet(id_wss_set_custom_channel,NO_ERROR,NULL,time);
        }
    }
    return wss_packet(id_wss_set_channel_spacing,COMM_TIMEOUT,param,0);
}

int set_test_wss(wss_device* p_wss){
    char recv[32] = {0};
    if(send_to_wss(p_wss,"TEST",recv,32,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
           return 1;
        }
    }
    return 0;     
}

cJSON* packet_temp_wss(wss_device* p_wss){
    cJSON* param = cJSON_CreateObject();    
    cJSON_AddItemToObject(param,"caseTemperature",cJSON_CreateString(p_wss->case_temp));
    cJSON_AddItemToObject(param,"internalTemperature",cJSON_CreateString(p_wss->inernal_temp));               
    return param;     
}

cJSON* get_temp_wss(wss_device* p_wss){
    char recv[32] = {0};
    if(send_to_wss(p_wss,"CSS?",recv,32,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            find_keys("\\^(-?[0-9]+\\.[0-9])\\$",recv,1,p_wss->case_temp);
        }
    }
    if(send_to_wss(p_wss,"ISS?",recv,32,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            find_keys("\\^(-?[0-9]+\\.[0-9])\\$",recv,1,p_wss->inernal_temp);
        }
    }
    return wss_packet(id_wss_get_temp,NO_ERROR,packet_temp_wss(p_wss),0); 
}

cJSON* get_info_wss(wss_device* p_wss){
    cJSON* param = cJSON_CreateObject();    
    cJSON_AddItemToObject(param,"fpgaVersion",cJSON_CreateString(p_wss->fpga_version));
    cJSON_AddItemToObject(param,"firmwareVersion",cJSON_CreateString(p_wss->firmware_version));
    cJSON_AddItemToObject(param,"serialNumber",cJSON_CreateString(p_wss->serial_number)); 
    cJSON_AddItemToObject(param,"manufacturingDate",cJSON_CreateString(p_wss->manufacturing_date));  
    cJSON_AddItemToObject(param,"moduleId",cJSON_CreateString(p_wss->module_id));                
    return wss_packet(id_wss_get_info,NO_ERROR,param,0);    
}

cJSON* custom_packet(wss_device* p_wss){
    int i,count;
    cJSON* root = cJSON_CreateObject();
    cJSON* array,*item;
    count = p_wss->channels_count;
    if(count > 0){
        array = cJSON_CreateArray();
        for(i=0;i<count;i++){
            item = cJSON_CreateObject();
            cJSON_AddItemToObject(item,"channelNumber",cJSON_CreateNumber(p_wss->channels[i].channel));
            cJSON_AddItemToObject(item,"portNumber",cJSON_CreateNumber(p_wss->channels[i].port));
            cJSON_AddItemToObject(item,"attenuation",cJSON_CreateNumber(p_wss->channels[i].atten));
            cJSON_AddItemToArray(array,item);             
        }                   
        cJSON_AddItemToObject(root,"infos",array);
    }    
    return root;
}

cJSON* get_channel_port_wss(wss_device* p_wss){
    char recv[32] = {0};
    int count = 0;
    if(send_to_wss(p_wss,"RCA",recv,32,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            string_to_channel(recv,p_wss->channels,&p_wss->channels_count);
            return wss_packet(id_wss_get_custom,NO_ERROR,custom_packet(p_wss),0);
        }
    }
    return wss_packet(id_wss_get_custom,COMM_TIMEOUT,NULL,0);
}

int wss_set_channel_port(wss_device* p_wss,clock_t* time){
    char buff[WSS_BUF_LENGTH] = {0};
    char send[WSS_BUF_LENGTH] = {0};
    channel_to_string(p_wss->channels,p_wss->channels_count,buff);
    
    sprintf(send,"UCA %s",buff);  
    memset(buff,0,WSS_BUF_LENGTH);      
    if(send_to_wss(p_wss,send,buff,32,5,time)){
        if(find_key(WSS_OK,buff,NULL,NULL,0,0)){ 
            store_data(p_wss);                
            return 1;
        }
    }
    return 0;   
}

cJSON* set_channel_port_wss(wss_device* p_wss,cJSON* param){
    cJSON* infos,*item;
    clock_t time;
    int i,size;
    wss_channel channels[WSS_CHANNEL_NUMBER];
    char buff[WSS_BUF_LENGTH];
    char send[WSS_BUF_LENGTH];
    char recv[32];

    infos = cJSON_GetObjectItem(param,"infos");
    if(infos){
        size = cJSON_GetArraySize(infos);              
        for(i=0;i<size;i++){
            item = cJSON_GetArrayItem(infos,i);
            channels[i].channel = cJSON_GetObjectItem(item,"channelNumber")->valueint;
            channels[i].port = cJSON_GetObjectItem(item,"port")->valueint;
            channels[i].atten = cJSON_GetObjectItem(item,"attenuation")->valuedouble;
        }
        
        if(wss_set_channel_port(p_wss,&time)){
            p_wss->channels_count = size;
            memcpy(p_wss->channels,channels,size*sizeof(wss_channel));
            wss_save_config(p_wss,0);
            return wss_packet(id_wss_set_custom,NO_ERROR,NULL,time);            
        }        
        return wss_packet(id_wss_set_custom,COMM_TIMEOUT,NULL,0);
    }
    return wss_packet(id_wss_set_custom,MISSING_PARAM,NULL,0);  
}

cJSON* reset_wss(wss_device* p_wss){
    char recv[32] = {0};
    int count = 0;
    if(send_to_wss(p_wss,"RES",recv,32,5,NULL)){
        if(find_key(WSS_OK,recv,NULL,NULL,0,0)){
            return wss_packet(id_wss_reset,NO_ERROR,custom_packet(p_wss),0);
        }
    }
    return wss_packet(id_wss_reset,COMM_TIMEOUT,NULL,0);  
}

//--------------------------

cJSON* wss_parse(CMD_ID id,cJSON* param){
    cJSON* wss_json = NULL;
 
    if(wss.busy) {
        return wss_packet(id,DEVICE_BUSY,NULL,0);
    }
    wss.busy = 1;
    switch(id){
        case id_wss_set_custom:
            wss_json = set_channel_port_wss(&wss,param);
        break;
        case id_wss_get_custom:
            wss_json = get_channel_port_wss(&wss);
        break;
        case id_wss_reset:	
            wss_json = reset_wss(&wss);
        break;
        case id_wss_get_temp:
            wss_json = get_temp_wss(&wss);
        break;
        case id_wss_get_info:
            wss_json = get_info_wss(&wss);
        break; 
        case id_wss_set_channel_spacing:
            wss_json = set_channel_spacing_wss(&wss,param);
        break;
        case id_wss_get_channel_spacing:
            wss_json = get_channel_spacing_wss(&wss);
        break;
        case id_wss_set_custom_channel:
            wss_json = set_custom_channel_wss(&wss,param);
        break;
        case id_wss_get_custom_channel:
            wss_json = get_custom_channel_wss(&wss);
        break;
        case id_save_default:
            wss_save_config(&wss,1);
        break;
        case id_load_default:
            wss_load_config(&wss,1);
            wss_set_spacing(&wss,wss.channel_spacing,NULL);
            wss_set_custom(&wss,wss.slices,wss.slices_count,NULL);
            wss_set_channel_port(&wss,NULL);  
            store_data(&wss);          
        break;        
    }
    wss.busy = 0; 
    return wss_json;
   
}

static void test(){

}

void* wss_thread(void* param){    
    init_wss(&wss);    
    init_wss_device(&wss);    

    // test();
    while(!wss.exit){
        if(wss.sample_flag){
            if(wss.busy) continue;
            wss.sample_flag = 0;
            wss_sample(&wss);
        }
        usleep(50*1000);
    }    
    return NULL;
}